package com.itheima;
/*
进程和线程
    进程:正在执行的应用程序

    线程:总的一条执行路径,或者说执行单元
        进程中只有一条执行路径,单线程
        如果有多条执行路径,多线程

同步代码块(锁)
    做法:把操作共享资源的代码块加锁,使得在某一时刻,只能一条线程操作共享资源
    锁对象,--任意对象
        保证唯一;多条线程使用同一把锁
同步方法



 */

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.locks.ReentrantLock;

public class Demo_Thread {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建类继承Thread,创建类对象
        /*MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        t1.start();
        t2.start();*/
        //创建一个参数对象,实现Runnable
        /*MyRunnable mr = new MyRunnable();
        //创建一个线程对象,执行参数里面的run方法
        Thread t1 = new Thread(mr);
        //开启线程
        t1.start();
        //MyRunnable mr2 = new MyRunnable();
        Thread t2 = new Thread(mr);
        t2.start();*/
        //创建一个类实现Callable
        /*MyCallable mc = new MyCallable();
        //获取线程执行完的结果,实现了Runnable,作为参数传给Thread对象
        FutureTask<String> ft = new FutureTask<>(mc);
        FutureTask<String> ft2 = new FutureTask<>(mc);
        //创建线程对象
        Thread t1 = new Thread(ft);
        Thread t2 = new Thread(ft2);
        //开启线程
        t1.start();
        t2.start();
        //获得结果
        String s = ft.get();
        System.out.println(s);
        String s2 = ft2.get();
        System.out.println(s2);*/
        //Thread常见方法
        //getName
        //setName
        /*MyThread t1 = new MyThread("阿强");
        MyThread t2 = new MyThread("阿珍");
//      t1.setName("阿强");
//      t2.setName("阿珍");
        t1.start();
        t2.start();*/
        //currentThread()获取当前线程对象
        /*MyRunnable mr = new MyRunnable();
        //创建一个线程对象,执行参数里面的run方法
        Thread t1 = new Thread(mr,"乔峰");
        //开启线程
        t1.start();
        //MyRunnable mr2 = new MyRunnable();
        Thread t2 = new Thread(mr,"慕容");
        t2.start();*/
        //Thread.sleep():线程休眠
        //setPriority设置优先级(1-10)
        /*MyCallable mc = new MyCallable();
        //获取线程执行完的结果,实现了Runnable,作为参数传给Thread对象
        FutureTask<String> ft = new FutureTask<>(mc);
        FutureTask<String> ft2 = new FutureTask<>(mc);
        //创建线程对象
        Thread t1 = new Thread(ft);
        Thread t2 = new Thread(ft2);
        //开启线程
        t1.setName("艾欧尼亚");
        t1.setPriority(10);
        t1.start();
        t2.setName("诺克萨斯");
        t2.setPriority(1);
        t2.start();
        //获得结果
        String s = ft.get();
        System.out.println(s);
        String s2 = ft2.get();
        System.out.println(s2);*/
        //setDaemon,守护线程,普通线程结束后,守护线程不会执行完毕
        //线程安全问题
        //创建ticket对象
        /*Ticket ticket = new Ticket();
        //创建线程对象并命名
        Thread t1 = new Thread(ticket, "一窗口");
        Thread t2 = new Thread(ticket, "二窗口");
        Thread t3 = new Thread(ticket, "三窗口");
        //开启线程
        t1.start();
        t2.start();
        t3.start();*/
        //同步代码块(锁)
        //死锁两条或多条线程,互相持有对方所需要的锁对象资源,
        // 造成所有线程都不能执行的现象
        //锁嵌套造成
        /*Object lockA = new Object();
        Object lockB = new Object();
        new Thread(() -> {
            while (true) {
                synchronized (lockA) {
                    synchronized (lockB) {
                        System.out.println("A散步");
                    }
                }
            }
        }).start();
        new Thread(() -> {
            while (true) {
                synchronized (lockB) {
                    synchronized (lockA) {
                        System.out.println("B散步");
                    }
                }
            }
        }).start();*/
        //生产者和消费者

    }
}

class MyThread extends Thread {
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            //System.out.println("线程启动"+i);
            System.out.println(getName() + "---" + i);
        }
    }
}

class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(100);//线程休眠
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "线程启动" + i);
        }
    }
}

class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "线程启动" + i);
        }
        return "结束";
    }
}

class Ticket implements Runnable {
    private int ticket = 100;
    ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            try {
                lock.lock();
                if (ticket == 0) {//负号票 t1 t2 t3
                    return;
                } else {
                    ticket--;
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "售出一张票,还剩" + ticket + "张");
                }
            } finally {
                lock.unlock();
            }
        }
    }
}
